home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
utility.lha
/
utility
/
strings.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-08
|
5KB
|
279 lines
// $Id: strings.C,v 1.4 92/01/09 11:26:01 dag Exp $
//
// NOTE: internal_buffer_size > 1 required by operator = (char).
#include <defs.H>
#include <strings.H>
#include <ctype.h>
#include <iostream.h>
// Set DO_STAT true to collect statistics on string lengths.
#define DO_STAT 0
#if DO_STAT
#include <statcount.H>
static void Count(int sz)
{
static StatCount cnt("Distribution of string sizes", 0, 64, 4);
cnt(sz);
}
#else
#define Count(size)
#endif
// The following macros handle allocation of string memory, either with
// the internal buffer of by allocating on the heap.
#define allocate(str, n) str = n <= internal_buffer_size ? buf : new char[n]
#define deallocate(str) if (str != buf) delete [] str
// ----------------------------------------------------------------------------
// Constructors, destructor
String :: String ()
{
size = internal_buffer_size;
allocate(str, internal_buffer_size);
Count(size);
str[0] = '\0';
}
String :: String (const char* s)
{
if (s == nil)
s = "";
size = max(strlen(s)+1, internal_buffer_size);
allocate(str, size);
Count(size);
strcpy(str, s);
}
String :: String (const String& s)
{
size = s.Size();
allocate(str, size);
Count(size);
strcpy(str, s.str);
}
String :: ~String()
{
deallocate(str);
}
// ----------------------------------------------------------------------------
// Assignment, assignment operators
String& String :: operator = (const String& s)
{
if (&s != this) { // same object?
int len = s.Length();
if (len >= size) {
size = len + 1;
deallocate(str);
allocate(str, size);
Count(size);
}
strcpy(str, s.str);
}
return *this;
}
String& String :: operator = (const char* s)
// Note: works even if s == this->str, although "strcpy" is not needed.
{
if (s == nil)
s = "";
int len = strlen(s);
if (len >= size) {
size = len + 1;
deallocate(str);
allocate(str, size);
Count(size);
}
strcpy(str, s);
return *this;
}
String& String :: operator = (char c)
{
str[0] = c;
str[1] = '\0';
return *this;
}
void String :: operator += (const String& s)
{
unsigned newlen = Length() + s.Length();
if (newlen < size)
strcat(str, s.str);
else {
size = newlen + internal_buffer_size;
char* r = new char[size];
Count(size);
strcpy(r, str);
strcat(r, s.str);
deallocate(str);
str = r;
}
}
void String :: operator += (char c)
{
const int chunk_size = internal_buffer_size;
unsigned oldlength = Length();
if (oldlength + 1 >= size) {
size += chunk_size;
char* r = new char[size];
Count(size);
strcpy(r, str);
deallocate(str);
str = r;
}
str[oldlength] = c;
str[oldlength+1] = '\0';
}
String operator + (const String& s1, const String& s2)
{
String r = s1;
r += s2;
return r;
}
// ----------------------------------------------------------------------------
// Subscripting
char String :: operator () (unsigned i) const
{
if (i < Length())
return str[i];
else
return '\0';
}
String String :: operator () (unsigned start, unsigned n) const
{
static char* r = 0; // temporary storage
delete r;
unsigned len = Length();
if (start >= len)
return "";
n = min(n, len-start);
r = new char[n + 1];
strncpy(r, str+start, n);
r[n] = 0;
return r;
}
// ----------------------------------------------------------------------------
// Comparisons
boolean operator == (const String& s1, const char* s2)
{
if (s2 == nil)
s2 = "";
return s1.str[0] == s2[0] && strcmp(s1.str, s2) == 0;
}
boolean operator == (char* s1, const String& s2)
{
if (s1 == nil)
s1 = "";
return s1[0] == s2.str[0] && strcmp(s1, s2.str) == 0;
}
// ----------------------------------------------------------------------------
// Misc. utility functions
char* String :: Copy() const
{
char* s = new char[Length() + 1];
strcpy(s, str);
return s;
}
String String :: upper() const
{
String t = *this;
register char* p = &t.str[t.Length()];
while (--p >= t.str)
if (islower(*p)) *p = toupper(*p);
return t;
}
String String :: lower() const
{
String t = *this;
register char* p = &t.str[t.Length()];
while (--p >= t.str)
if (isupper(*p)) *p = tolower(*p);
return t;
}
unsigned String :: Hashval() const
{
register char* p = str;
register unsigned h = 0;
while (*p != 0)
h += unsigned(*(p++));
return h;
}
// ----------------------------------------------------------------------------
// Input/output on streams
ostream& operator << (ostream& o, const String& s)
{
o << s.str;
return o;
}
istream& operator >> (istream& i, String& s)
{
char c;
s = "";
while (i.get(c) && isspace(c)) // skip to next word
;
if (i) { // read a word
do
s += c;
while (i.get(c) && !isspace(c));
if (i)
i.putback(c);
}
return i;
}